/*Trabalho1 - Programação Concorrente - Grupo04 Turma B
	Daniel Rodrigues Hatanaka - 7277579
	Guilherme Elias Guimarães Kalatzis Sousa – 7239426
	Thiago Fujisaka Tanaka - 7153014
Basta compilar o main.c que ele está associado com os arquivos .h necessários

LINUX:

gcc -pthread main.c -lgmp

MAC OS:

gcc main.c -lgmp

*/
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <math.h>
#include <sys/time.h>
#include <time.h>

struct timeval inicio,final;

mpf_t a0;
mpf_t b0;
mpf_t t0;
mpf_t p0;
mpf_t a1;
mpf_t b1;
mpf_t t1;
mpf_t p1;
mpf_t pi;
mpf_t piAnterior;
mpf_t temp1;
mpf_t temp2;


void calculoAsequencial(){
	mpf_add(a1,a0,b0);
    mpf_div_ui (a1,a1,2);


}

void calculoBsequencial(){
	mpf_mul (b1,a0,b0);
    mpf_sqrt (b1,b1);


}

void calculoTsequencial(){
	mpf_sub (temp1, a0, a1);
    mpf_pow_ui (temp2,temp1,2);
    mpf_mul (temp1,p0,temp2);
    mpf_sub (t1, t0, temp1);

}

void calculoPsequencial(){
	mpf_mul_ui(p1,p0,2);

}

void atualizaVariaveis(){
	mpf_swap (a0,a1);
    mpf_swap (b0,b1);
    mpf_swap (t0,t1);
    mpf_swap (p0,p1);


}

void calculaPiSequencial(){
	mpf_add(pi,a1,b1);
    mpf_pow_ui (pi,pi,2);
    mpf_mul_ui(temp1,t1,4);
    mpf_div (pi,pi,temp1);
}

void destrutor(){
    mpf_clear(piAnterior);
    mpf_clear(a0);
    mpf_clear(b0);
    mpf_clear(t0);
    mpf_clear(p0);
    mpf_clear(a1);
    mpf_clear(b1);
    mpf_clear(t1);
    mpf_clear(p1);
    mpf_clear(pi);
    mpf_clear(temp1);
    mpf_clear(temp2);
}

void GaussLegendreSeq(){
    //Abertura do arquivo que iremos salvar o valor de pi
    FILE *GaussLegendreSeq;
    GaussLegendreSeq = fopen("gaussLegendreSequencial.txt", "w+");
    unsigned int cont=0;
    int time;

	//Precisão log10*10.000.000 = 33.000.000 aproximando para cima para 34milhoes
    mpf_set_default_prec (34000000);

   	//mpf_inits(piAnterior,a0,b0,t0,p0,a1,b1,t1,p1,pi,temp1,temp2);
   	//Iniciar variaveis assim da bus error
    mpf_init(piAnterior);
    mpf_init(a0);
    mpf_init(b0);
    mpf_init(t0);
    mpf_init(p0);
    mpf_init(a1);
    mpf_init(b1);
    mpf_init(t1);
    mpf_init(p1);
    mpf_init(pi);
    mpf_init(temp1);
    mpf_init(temp2);

    gettimeofday(&inicio, NULL);
    //Iniciando a0
    mpf_set_d (a0,1);
 	//Iniciando b0

 	mpf_sqrt_ui(temp1,2);
    mpf_ui_div(b0, 1, temp1);
    //Iniciando t0
	mpf_div_ui(t0,a0,4);

    //Iniciando p0
    mpf_set_d (p0,1);

    for(;;){
	//Calculo de a1
        calculoAsequencial();

	//Calculo de b1
        calculoBsequencial();
	//Calculo de t1
        calculoTsequencial();

	//Calculo de p1
       	calculoPsequencial();

	//Girando os valores
        atualizaVariaveis();

    //Calculando pi
    	calculaPiSequencial();
    	if(mpf_eq(pi, piAnterior, 34000000)) {
    			gmp_printf("pi calculado = %.10000000Ff\n",pi);
				mpf_out_str(GaussLegendreSeq,10,10000000,pi);
				break;
		}
    	mpf_swap (piAnterior,pi);
    	cont++;
    }
    gettimeofday(&final, NULL);
	time = final.tv_sec - inicio.tv_sec;

    printf("Contador de iterações %i\n\n", cont);

    printf("Tempo em %i segundos\n",time);


    //Limpa variaveis
    destrutor();

}
